package ch.uzh.ifi.seal.ssqa.ui.views;

import java.util.Iterator;
import java.util.List;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.gmf.runtime.diagram.core.listener.DiagramEventBroker;
import org.eclipse.gmf.runtime.diagram.core.preferences.PreferencesHint;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramRootEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IDiagramPreferenceSupport;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramCommandStack;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditDomain;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramGraphicalViewer;
import org.eclipse.gmf.runtime.diagram.ui.services.editpart.EditPartService;
import org.eclipse.gmf.runtime.emf.core.resources.GMFResource;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.gmf.runtime.notation.MeasurementUnit;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.part.ViewPart;

import ch.uzh.ifi.seal.ssqa.SsqaPlugin;
import ch.uzh.ifi.seal.ssqa.model.DiagramComponent;
import ch.uzh.ifi.seal.ssqa.model.diagram.edit.parts.SsqaEditPartFactory;
import ch.uzh.ifi.seal.ssqa.model.diagram.part.SsqaDiagramEditorPlugin;
import ch.uzh.ifi.seal.ssqa.popup.actions.OpenElementMetricsViewAction;
import ch.uzh.ifi.seal.ssqa.popup.actions.OpenFileModelViewAction;
import ch.uzh.ifi.seal.ssqa.popup.actions.OpenSourceChangeCouplingAction;
import ch.uzh.ifi.seal.ssqa.popup.actions.ReloadArchitectureAnalysisAction;
import ch.uzh.ifi.seal.ssqa.preferences.PreferenceConstants;

public class ArchitectureAnalysisView extends ViewPart {
	public static final String ID = "ch.uzh.ifi.seal.ssqa.ui.views.ArchitectureAnalysisView";

	private String resourceURI;

	private DiagramGraphicalViewer viewer;
	
	private Composite parent; 
	
	private List<DiagramComponent> components; 

	public void createPartControl(Composite parent) {
		this.parent = parent;
		
		IPreferenceStore store = SsqaPlugin.getDefault().getPreferenceStore();
		this.resourceURI = store.getString(PreferenceConstants.ANALYSIS_DEFAULT_ARCH_FILE);
		
		viewer = new DiagramGraphicalViewer();
		viewer.createControl(parent);
		viewer.getControl().setBackground(ColorConstants.listBackground);
		DiagramEditDomain editDomain = new DiagramEditDomain(null);
		editDomain.setCommandStack(new DiagramCommandStack(editDomain));
		viewer.setEditDomain(editDomain);
		viewer.setRootEditPart(new DiagramRootEditPart(MeasurementUnit.PIXEL_LITERAL));
		
		IAction action = new ReloadArchitectureAnalysisAction(parent.getShell());
		IActionBars actionBars = getViewSite().getActionBars();
		IToolBarManager toolBar = actionBars.getToolBarManager();
		toolBar.add(action);

		if(this.resourceURI != "" && this.resourceURI != null){
			this.loadViewDiagram();
		}
	}
	
	public String getResourceURI(){
		return this.resourceURI;
	}

	public void loadViewDiagram() {
		Diagram diagram = this.getDiagramForResource(this.resourceURI);
		DiagramRootEditPart rootEP = (DiagramRootEditPart) EditPartService.getInstance().createRootEditPart(diagram);
		
		PreferencesHint preferencesHint = SsqaDiagramEditorPlugin.DIAGRAM_PREFERENCES_HINT;
		
        if (rootEP instanceof IDiagramPreferenceSupport) {
            if (preferencesHint == null) {
                preferencesHint = ((IDiagramPreferenceSupport) rootEP)
                    .getPreferencesHint();
            } else {
                ((IDiagramPreferenceSupport) rootEP)
                    .setPreferencesHint(preferencesHint);
            }
            this.viewer.hookWorkspacePreferenceStore((IPreferenceStore) preferencesHint.getPreferenceStore());
        } else {
        	this.viewer.hookWorkspacePreferenceStore(SsqaDiagramEditorPlugin.getInstance().getPreferenceStore());
        }

        
	    this.viewer.setRootEditPart(rootEP);
	    this.viewer.setEditPartFactory(new SsqaEditPartFactory());

	    DiagramEventBroker.startListening(TransactionUtil.getEditingDomain(diagram));
	    this.viewer.setContents(diagram);
	    this.viewer.flush();
		
		DiagramEditPart diagEP = (DiagramEditPart) this.viewer.getContents();
		
		diagEP.disableEditMode();
		MenuManager contextMenu = new MenuManager();
		contextMenu.add(new OpenFileModelViewAction());
		contextMenu.add(new OpenElementMetricsViewAction());
		contextMenu.add(new OpenSourceChangeCouplingAction());
		this.viewer.setContextMenu(contextMenu);
		
		this.getSite().setSelectionProvider(viewer);
		
		double width = (double)this.parent.getBounds().width/((double)diagEP.getFigure().getBounds().width+20);
		
		if(width != 0){
			rootEP.getZoomManager().setZoom(width);
		} else {
			rootEP.getZoomManager().setZoom(0.8);
		}
	}

	/**
	 * setting a plugin dependant URI
	 * 
	 * @param resourceURI
	 */
	public void setResourceURI(String resourceURI) {
		this.resourceURI = resourceURI;
	}

	private Diagram getDiagramForResource(String resourceUri) {
		ResourceSet resSet = new ResourceSetImpl();
		TransactionalEditingDomain.Factory.INSTANCE.createEditingDomain(resSet);
		GMFResource resource = (GMFResource) resSet.getResource(URI.createPlatformResourceURI(this.resourceURI, true), true);
		Diagram diagram = null;
		Iterator<EObject> iterator = resource.getContents().iterator();
		while (iterator.hasNext()) {
			EObject object = iterator.next();
			if (object instanceof Diagram) {
				diagram = (Diagram) object;
			}
		}
		return diagram;
	}
	
	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
	}
	
	public DiagramGraphicalViewer getViewer(){
		return this.viewer;
	}
	
}
